extern crate std as ruststd;

use core::hash::{self, Hash};
use core::intrinsics::{arith_offset, assume};
use core::iter::FromIterator;
use core::mem;
use core::ops::{Index, IndexMut};

const CAPACITY: usize = 2 * B - 1;

fn foo(a: i32, b: str, c: i32, d: f32) -> () {
    let mut e: &'static [str] = "abcd";
    let mut f: &[str] = "cdef";
    bar();
    let array: [i32; 45] = [0; 45];
    let f: fn(i32, u64) -> i32;
    let f2: fn(i32) -> i32;
    let unit: () = ();
    let foo = 2 + 2;
    let moo = 2 * 2;
    let meh = 2 * 2 + 3 * 3;
    else_block.as_ref().map(|e| &**e);
    match self.node {
        ast::ExprKind::Field(..) |
        ast::ExprKind::MethodCall(..) => rewrite_chain(self, context, width, offset)
    };
    let f: fn(&_, _) -> _ = unimplemented!();
    let f = unimplemented! {};
    {
        foo();
    }
    for &(sample, radiance) in samples.iter() {}
    map(|&s| moo());
    match x {
        S { foo } => 92
    }
}

enum Message {
    Quit,
    ChangeColor(i32, i32, i32),
    Move { x: i32, y: i32 },
    Write(String),
}

enum Foo {
    Bar = 123,
    Baz = 0,
}

pub struct Vec<T> {
    buf: RawVec<T>,
    len: usize,
}

impl<T> Vec<T> {
    pub fn new() -> Vec<T> {
        Vec {
            buf: RawVec::new(),
            len: 0,
        }
    }

    pub fn with_capacity(capacity: usize) -> Vec<T> {
        Vec {
            buf: RawVec::with_capacity(capacity),
            len: 0,
        }
    }

    pub unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usize) -> Vec<T> {
        Vec {
            buf: RawVec::from_raw_parts(ptr, capacity),
            len: length,
        }
    }

    pub fn capacity(&self) -> usize {
        self.buf.cap()
    }

    pub fn reserve(&mut self, additional: usize) {
        self.buf.reserve(self.len, additional);
    }

    pub fn into_boxed_slice(mut self) -> Box<[T]> {
        unsafe {
            self.shrink_to_fit();
            let buf = ptr::read(&self.buf);
            mem::forget(self);
            buf.into_box()
        }
    }

    pub fn truncate(&mut self, len: usize) {
        unsafe {
            while len < self.len {
                self.len -= 1;
                let len = self.len;
                ptr::drop_in_place(self.get_unchecked_mut(len));
            }
        }
    }

    pub fn as_slice(&self) -> &[T] {
        self
    }

    pub fn as_mut_slice(&mut self) -> &mut [T] {
        &mut self[..]
    }

    pub unsafe fn set_len(&mut self, len: usize) {
        self.len = len;
    }

    pub fn remove(&mut self, index: usize) -> T {
        let len = self.len();
        assert!(index < len);
        unsafe {
            let ret;
            {
                let ptr = self.as_mut_ptr().offset(index as isize);
                ret = ptr::read(ptr);
                ptr::copy(ptr.offset(1), ptr, len - index - 1);
            }
            self.set_len(len - 1);
            ret
        }
    }

    pub fn retain<F>(&mut self, mut f: F) where F: FnMut(&T) -> bool
    {
        let len = self.len();
        let mut del = 0;
        {
            let v = &mut **self;

            for i in 0..len {
                if !f(&v[i]) {
                    del += 1;
                } else if del > 0 {
                    v.swap(i - del, i);
                }
            }
        }
        if del > 0 {
            self.truncate(len - del);
        }
    }

    pub fn drain<R>(&mut self, range: R) -> Drain<T> where R: RangeArgument<usize> {
        let len = self.len();
        let start = *range.start().unwrap_or(&0);
        let end = *range.end().unwrap_or(&len);
        assert!(start <= end);
        assert!(end <= len);
    }
}

impl<T: Clone> Vec<T> {
    pub fn extend_from_slice(&mut self, other: &[T]) {
        self.reserve(other.len());

        for i in 0..other.len() {
            let len = self.len();

            unsafe {
                ptr::write(self.get_unchecked_mut(len), other.get_unchecked(i).clone());
                self.set_len(len + 1);
            }
        }
    }
}

impl<T: PartialEq> Vec<T> {
    pub fn dedup(&mut self) {
        unsafe {
            let ln = self.len();
            if ln <= 1 {
                return;
            }

            let p = self.as_mut_ptr();
            let mut r: usize = 1;
            let mut w: usize = 1;

            while r < ln {
                let p_r = p.offset(r as isize);
                let p_wm1 = p.offset((w - 1) as isize);
                if *p_r != *p_wm1 {
                    if r != w {
                        let p_w = p_wm1.offset(1);
                        mem::swap(&mut *p_r, &mut *p_w);
                    }
                    w += 1;
                }
                r += 1;
            }

            self.truncate(w);
        }
    }
}

pub fn from_elem<T: Clone>(elem: T, n: usize) -> Vec<T> {}

impl<T: Clone> Clone for Vec<T> {
    fn clone(&self) -> Vec<T> {
        <[T]>::to_vec(&**self)
    }

    fn clone(&self) -> Vec<T> {
        ::slice::to_vec(&**self)
    }

    fn clone_from(&mut self, other: &Vec<T>) {
        self.truncate(other.len());
        let len = self.len();
        self.clone_from_slice(&other[..len]);
        self.extend_from_slice(&other[len..]);
    }
}

impl<T: Hash> Hash for Vec<T> {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        Hash::hash(&**self, state)
    }
}

impl<T> Index<usize> for Vec<T> {
    type Output = T;

    fn index(&self, index: usize) -> &T {
        &(**self)[index]
    }
}

impl<T> IndexMut<usize> for Vec<T> {
    fn index_mut(&mut self, index: usize) -> &mut T {
        &mut (**self)[index]
    }
}

impl<T> FromIterator<T> for Vec<T> {
    fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> Vec<T> {
        let mut iterator = iter.into_iter();
        let mut vector = match iterator.next() {
            None => return Vec::new(),
            Some(element) => {
                let (lower, _) = iterator.size_hint();
                // ...
            }
        };
        // ...
    }
}

impl<T> IntoIterator for Vec<T> {
    type Item = T;
    type IntoIter = IntoIter<T>;

    fn into_iter(mut self) -> IntoIter<T> {
        unsafe {
            let ptr = self.as_mut_ptr();
            assume(!ptr.is_null());
            let begin = ptr as *const T;
            let end = if mem::size_of::<T>() == 0 {
                arith_offset(ptr as *const i8, self.len() as isize) as *const T
            } else {
                ptr.offset(self.len() as isize) as *const T
            };
            let buf = ptr::read(&self.buf);
            mem::forget(self);
            IntoIter {
                _buf: buf,
                ptr: begin,
                end: end,
            }
        }
    }
}

impl<'a, T> IntoIterator for &'a Vec<T> {
    type Item = &'a T;
}

impl<T> Iterator for IntoIter<T> {
    fn size_hint(&self) -> (usize, Option<usize>) {
        let diff = (self.end as usize) - (self.ptr as usize);
        let size = mem::size_of::<T>();
        let exact = diff / (if size == 0 { 1 } else { size });
        (exact, Some(exact))
    }
}

impl<'a, T> Iterator for Drain<'a, T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        self.iter.next().map(|elt| unsafe { ptr::read(elt as *const _) })
    }
}

trait Extend<A> {
    fn extend<T: IntoIterator<Item=A>>(&mut self, iterable: T);
}

impl<R, F: FnOnce() -> R> FnOnce<()> for AssertRecoverSafe<F> {
    extern "rust-call" fn call_once(self, _args: ()) -> R {
        (self.0)()
    }
}

fn catch_unwind<F: FnOnce() -> R + UnwindSafe, R>(f: F) -> Result<R> {
    let mut result = None;
    unsafe {
        let result = &mut result;
        unwind::try(move || *result = Some(f()))?
    }
    Ok(result.unwrap())
}

fn propagate(payload: Box<Any + Send>) -> ! {}

impl<K, V> Root<K, V> {
    pub fn as_ref(&self) -> NodeRef<marker::Immut, K, V, marker::LeafOrInternal> {
        NodeRef {
            root: self as *const _ as *mut _,
        }
    }
}

macro_rules! vec {
    ( $( $x:expr ),* ) => {
        {
            let mut temp_vec = Vec::new();
            $(
                temp_vec.push($x);
            )*
            temp_vec
        }
    };
}

mod math {
    type Complex = (f64, f64);

    fn sin(f: f64) -> f64 {
        /* ... */
    }
}

fn foo(&&(x, _): &&(i32, i32)) {}
